package com.tenbent.product.base.common;

import com.tenbent.product.base.constants.WebConstans;
import com.tenbent.product.base.exception.*;
import com.tenbent.product.base.exception.Error;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import javax.servlet.http.HttpServletRequest;

/**
 * 控制器异常通知类处理所有控制器异常
 *
 * @author Randy
 *
 *         Created by ThinkPad on 2017/7/25.
 */
@ControllerAdvice
public class TenbentControllerAdvice {

	private static final Logger logger = LoggerFactory.getLogger(TenbentControllerAdvice.class);

	private static final String SERVER_ERROR = "Server Error";
	private static final String BAD_REQUEST_ERROR = "Bad Request Error";
	private static final String NOT_FOUND_ERROR = "Not Fount Error";
	/** 用于判断是rest API 接口 还是 视图 */
	private static final String API_REQUEST = "/api";
	private static final String DEFAULT_MESSAGE = "server is error !";

	@ModelAttribute(WebConstans.BIZ_MANAGER_ID)
	public Integer addAttributes(HttpServletRequest request) {
		Integer managerId = (Integer) request.getSession().getAttribute(WebConstans.LOGIN_ID);
		return managerId != null ? managerId : 8888;
	}

	@ExceptionHandler(Exception.class)
	public Object exception(HttpServletRequest request, Exception e, Model model) {
		// ResponseStatus responseStatus =
		// AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class);
		logger(SERVER_ERROR, 500, e.getMessage() != null ? e.getMessage() : DEFAULT_MESSAGE, e);
		String path = request.getServletPath();
		return path.contains(API_REQUEST)
				? tenbentApiException(
						new TenbentApiException(500, e.getMessage() != null ? e.getMessage() : DEFAULT_MESSAGE))
				: tenbentException(new TenbentException(500, e.getMessage()), model);
	}

	@ExceptionHandler(TenbentBadRequestException.class)
	public String tenbentBadRequestException(TenbentBadRequestException e, Model model) {
		logger(BAD_REQUEST_ERROR, e.getCode(), e.getMessage(), e, model);
		return "error/error";
	}

	@ExceptionHandler(TenbentNotFoundException.class)
	public String tenbentNotFoundException(TenbentNotFoundException e, Model model) {
		logger(NOT_FOUND_ERROR, e.getCode(), e.getMessage(), e, model);
		return "error/not_fount";
	}

	@ExceptionHandler(TenbentException.class)
	public String tenbentException(TenbentException e, Model model) {
		logger(SERVER_ERROR, e.getCode(), e.getMessage(), e, model);
		return "error/error";
	}

	@ExceptionHandler(TenbentApiNotFoundException.class)
	public ResponseEntity<Error> tenbentApiNotFoundException(TenbentApiNotFoundException e) {
		logger(NOT_FOUND_ERROR, e.getCode(), e.getMessage(), e);
		Error error = new Error(e.getCode(), e.getMessage());
		return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
	}

	@ExceptionHandler(TenbentApiException.class)
	public ResponseEntity<Error> tenbentApiException(TenbentApiException e) {
		logger(SERVER_ERROR, e.getCode(), e.getMessage(), e);
		Error error = new Error(e.getCode(), e.getMessage());
		return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
	}

	@ExceptionHandler(TenbentApiBadRequestException.class)
	public ResponseEntity<Error> tenbentApiBadRequestException(TenbentApiBadRequestException e) {
		logger(BAD_REQUEST_ERROR, e.getCode(), e.getMessage(), e);
		Error error = new Error(e.getCode(), e.getMessage());
		return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
	}

	private void logger(String desc, Integer code, String message, Throwable e) {
		e.printStackTrace();
		logger.error(String.format("%s, Code %s Message %s", desc, code, message), e);
	}

	private void logger(String desc, Integer code, String message, Throwable e, Model model) {
		logger(desc, code, message, e);
		model.addAttribute("error", code);
		model.addAttribute("message", message);
	}

}
